﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Pg.BioMedics.SDR.Entities;
using Pg.BioMedics.SDR.Entities.Codes;
using Pg.BioMedics.SDR.Services.Thesaurus;

namespace Pg.BioMedics.SDR.Services
{
    /// <summary>
    /// Provides static utility methods supporting tokens manipulation
    /// </summary>
    internal static class TokenHelper
    {
        #region Utility methods

        /// <summary>
        /// Extracts list of tokens from the provided textual content
        /// </summary>
        /// <param name="text">Textual content</param>
        /// <returns>List of tokens</returns>
        internal static IList<Token> ExtractTokens(string text)
        {
            if (String.IsNullOrEmpty(text))
                return new List<Token>();

            string[] tokenStrings = text.ToLower().Split(' ');
            string[] distinctTokenStrings = tokenStrings.Distinct().ToArray();
            int index = 0;
            return (from tokenString in tokenStrings
                    let occurances = (from occuranceTokenString in tokenStrings
                                      where occuranceTokenString == tokenString
                                      select occuranceTokenString).Count()
                    let offset = index++
                    select new Token()
                    {
                        Value = tokenString,
                        Offset = offset,
                        Probability = (double)occurances / (double)tokenStrings.Length,
                        AcousticScore = 0,
                        TypeCode = TokenTypeCodes.Word
                    }).ToList();
        }

        /// <summary>
        /// Removes from the tokens list all tokens which value stands on the 
        /// stop words list in the thesaurus
        /// </summary>
        /// <param name="tokens">List of tokens with which may contain stop tokens</param>
        /// <returns>List of word tokens without stop tokens</returns>
        internal static IList<Token> RemoveStopTokens(IList<Token> tokens)
        {
            return (from token in tokens
                    where (!token.Value.IsStopWord()) && (token.TypeCode == TokenTypeCodes.Word)
                    select token).ToList();
        }

        /// <summary>
        /// Expands list of tokens with tokens synonyms extracted from the Thesaurus
        /// </summary>
        /// <param name="tokens">List of input tokens</param>
        /// <returns>List of tokens expanded with synonyms</returns>
        internal static IList<Token> ExpandWithSynonyms(IList<Token> tokens)
        {
            return (from token in tokens
                    from synonym in token.Value.FindAllSynonyms()
                    from synonymToken in synonym.Split(' ')
                    let internalSynonymToken = synonymToken.Trim().ToLower()
                    where !synonymToken.IsStopWord() && (synonym != token.Value)
                    select new Token()
                    {
                        Value = internalSynonymToken,
                        Probability = token.Probability,
                        Offset = token.Offset,
                        AcousticScore = token.AcousticScore,
                        TypeCode = token.TypeCode
                    }).Union(tokens)
                      .ToList();
        }

        #endregion
    }
}
